package http.util;

import org.springframework.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ReflectionUtil {


    public static void mapFillPojo(Map<String,Object> map, Object obj) throws IllegalAccessException {
        if(CollectionUtils.isEmpty(map)){
            return ;
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        if(fields == null || fields.length == 0){
            return ;
        }
        for (Field f : fields) {
            Object val =map.get(f.getName());
            if(val != null){
                f.setAccessible(true);
                f.set(obj,val);
            }
        }
    }
    public static <T>T mapToPojo(Map<String,Object> map,Class<T> clazz) throws IllegalAccessException, InstantiationException {
        T t = clazz.newInstance();
        if(CollectionUtils.isEmpty(map)){
            return t;
        }
        Field[] fields = clazz.getDeclaredFields();
        if(fields == null || fields.length == 0){
            return t;
        }
        for (Field f : fields) {
            Object val =map.get(f.getName());
            if(val != null){
                f.setAccessible(true);
                f.set(t,val);
            }
        }
        return t;
    }
    public static Map<String,Object> pojoToMap(Object obj) throws IllegalAccessException {
        Map<String,Object> map=new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        if(fields == null || fields.length == 0){
            return map;
        }
        for (Field f : fields) {
            f.setAccessible(true);
            Object val = f.get(obj);
            if(val != null){
                map.put(f.getName(),val);
            }
        }
        return map;
    }
    public static List<Method> getMethodByAnnotation(Class<?> clazz, Class<? extends Annotation> annotaionClass) {
        List<Method> result = new ArrayList<>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            Annotation annotation = method.getAnnotation(annotaionClass);
            if (annotation == null) {
                continue;
            }
            result.add(method);
        }
        return result;
    }

    public static <T extends Number> T converToNumberType(Object val, Class<T> targetClass) {
        Object value = null;
        if (Byte.class == targetClass) {
            value = Byte.valueOf(val.toString());
        }else if (Short.class == targetClass) {
            value = Short.valueOf(val.toString());
        }else if (Integer.class == targetClass) {
            value = Integer.valueOf(val.toString());
        }else if (Float.class == targetClass) {
            value = Float.valueOf(val.toString());
        }else if (Double.class == targetClass) {
            value = Double.valueOf(val.toString());
        }else if (BigInteger.class == targetClass) {
            value = BigInteger.valueOf(Long.parseLong(val.toString()));
        }else if (BigDecimal.class == targetClass) {
            value = BigDecimal.valueOf(Long.parseLong(val.toString()));
        }else {
            throw new IllegalArgumentException("Could not convert val [" + val + "] of type [" +
                    val.getClass().getName() + "] to unsupported target class [" + targetClass.getName() + "]");
        }
        return (T) value;
    }

    public static boolean isNumberType(Class<?> clazz) {
        return Number.class.isAssignableFrom(clazz);
    }


}
